import java.time.LocalDateTime;
import java.util.*;

// 1. 枚举定义
enum DataScope {
    PERSONAL("个人"), DEPARTMENT("部门"), GLOBAL("全局");

    private final String description;

    DataScope(String description) {
        this.description = description;
    }

    public String getDescription() {
        return description;
    }

    // 根据描述获取对应的枚举值
    public static DataScope fromDescription(String description) {
        for (DataScope scope : values()) {
            if (scope.description.equals(description)) {
                return scope;
            }
        }
        return null;
    }
}

// 2. 实体类定义
abstract class Entity {
    protected Integer id;
    protected LocalDateTime createTime;
    protected LocalDateTime updateTime;

    public Integer getId() { return id; }
    public void setId(Integer id) { this.id = id; }

    public LocalDateTime getCreateTime() { return createTime; }
    public void setCreateTime(LocalDateTime createTime) { this.createTime = createTime; }

    public LocalDateTime getUpdateTime() { return updateTime; }
    public void setUpdateTime(LocalDateTime updateTime) { this.updateTime = updateTime; }
}

class Dept extends Entity {
    private String name;
    private String phone;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public String getPhone() { return phone; }
    public void setPhone(String phone) { this.phone = phone; }
}

class Role extends Entity {
    private String name;
    private DataScope dataScope;

    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public DataScope getDataScope() { return dataScope; }
    public void setDataScope(DataScope dataScope) { this.dataScope = dataScope; }
}

class User extends Entity {
    private String username;
    private String password;
    private Role role;
    private Dept dept;
    private Boolean enabled;

    public String getUsername() { return username; }
    public void setUsername(String username) { this.username = username; }

    public String getPassword() { return password; }
    public void setPassword(String password) { this.password = password; }

    public Role getRole() { return role; }
    public void setRole(Role role) { this.role = role; }

    public Dept getDept() { return dept; }
    public void setDept(Dept dept) { this.dept = dept; }

    public Boolean getEnabled() { return enabled; }
    public void setEnabled(Boolean enabled) { this.enabled = enabled; }
}

// 3. DAO层
interface DeptDao {
    void save(Dept dept);
    List<Dept> findAll();
    Dept findById(Integer id);
    void update(Dept dept);
    void delete(Integer id);
}

class MemoryDeptDao implements DeptDao {
    private final Map<Integer, Dept> depts = new HashMap<>();
    private Integer nextId = 1;

    @Override
    public void save(Dept dept) {
        dept.setId(nextId++);
        dept.setCreateTime(LocalDateTime.now());
        depts.put(dept.getId(), dept);
    }

    @Override
    public List<Dept> findAll() {
        return new ArrayList<>(depts.values());
    }

    @Override
    public Dept findById(Integer id) {
        return depts.get(id);
    }

    @Override
    public void update(Dept dept) {
        dept.setUpdateTime(LocalDateTime.now());
        depts.put(dept.getId(), dept);
    }

    @Override
    public void delete(Integer id) {
        depts.remove(id);
    }
}

interface RoleDao {
    void save(Role role);
    List<Role> findAll();
    Role findById(Integer id);
    void update(Role role);
    void delete(Integer id);
}

class MemoryRoleDao implements RoleDao {
    private final Map<Integer, Role> roles = new HashMap<>();
    private Integer nextId = 1;

    @Override
    public void save(Role role) {
        role.setId(nextId++);
        role.setCreateTime(LocalDateTime.now());
        roles.put(role.getId(), role);
    }

    @Override
    public List<Role> findAll() {
        return new ArrayList<>(roles.values());
    }

    @Override
    public Role findById(Integer id) {
        return roles.get(id);
    }

    @Override
    public void update(Role role) {
        role.setUpdateTime(LocalDateTime.now());
        roles.put(role.getId(), role);
    }

    @Override
    public void delete(Integer id) {
        roles.remove(id);
    }
}

interface UserDao {
    void save(User user);
    List<User> findAll();
    User findById(Integer id);
    User findByUsername(String username);
    void update(User user);
    void delete(Integer id);
}

class MemoryUserDao implements UserDao {
    private final Map<Integer, User> users = new HashMap<>();
    private Integer nextId = 1;

    @Override
    public void save(User user) {
        user.setId(nextId++);
        user.setCreateTime(LocalDateTime.now());
        users.put(user.getId(), user);
    }

    @Override
    public List<User> findAll() {
        return new ArrayList<>(users.values());
    }

    @Override
    public User findById(Integer id) {
        return users.get(id);
    }

    @Override
    public User findByUsername(String username) {
        return users.values().stream()
                .filter(user -> user.getUsername().equals(username))
                .findFirst()
                .orElse(null);
    }

    @Override
    public void update(User user) {
        user.setUpdateTime(LocalDateTime.now());
        users.put(user.getId(), user);
    }

    @Override
    public void delete(Integer id) {
        users.remove(id);
    }
}

// 4. Service层
interface DeptService {
    void create(Dept dept);
    List<Dept> list();
    Dept getById(Integer id);
    void update(Dept dept);
    void delete(Integer id);
}

class DeptServiceImpl implements DeptService {
    private static DeptServiceImpl instance;
    private final DeptDao deptDao;

    private DeptServiceImpl(DeptDao deptDao) {
        this.deptDao = deptDao;
    }

    public static synchronized DeptServiceImpl getInstance(DeptDao deptDao) {
        if (instance == null) {
            instance = new DeptServiceImpl(deptDao);
        }
        return instance;
    }

    @Override
    public void create(Dept dept) {
        deptDao.save(dept);
    }

    @Override
    public List<Dept> list() {
        return deptDao.findAll();
    }

    @Override
    public Dept getById(Integer id) {
        return deptDao.findById(id);
    }

    @Override
    public void update(Dept dept) {
        deptDao.update(dept);
    }

    @Override
    public void delete(Integer id) {
        deptDao.delete(id);
    }
}

interface RoleService {
    void create(Role role);
    List<Role> list();
    Role getById(Integer id);
    void update(Role role);
    void delete(Integer id);
}

class RoleServiceImpl implements RoleService {
    private static RoleServiceImpl instance;
    private final RoleDao roleDao;

    private RoleServiceImpl(RoleDao roleDao) {
        this.roleDao = roleDao;
    }

    public static synchronized RoleServiceImpl getInstance(RoleDao roleDao) {
        if (instance == null) {
            instance = new RoleServiceImpl(roleDao);
        }
        return instance;
    }

    @Override
    public void create(Role role) {
        roleDao.save(role);
    }

    @Override
    public List<Role> list() {
        return roleDao.findAll();
    }

    @Override
    public Role getById(Integer id) {
        return roleDao.findById(id);
    }

    @Override
    public void update(Role role) {
        roleDao.update(role);
    }

    @Override
    public void delete(Integer id) {
        roleDao.delete(id);
    }
}

interface UserService {
    void create(User user);
    List<User> list();
    User getById(Integer id);
    User getByUsername(String username);
    void update(User user);
    void delete(Integer id);
}

class UserServiceImpl implements UserService {
    private static UserServiceImpl instance;
    private final UserDao userDao;
    private final DeptService deptService;
    private final RoleService roleService;

    private UserServiceImpl(UserDao userDao, DeptService deptService, RoleService roleService) {
        this.userDao = userDao;
        this.deptService = deptService;
        this.roleService = roleService;
    }

    public static synchronized UserServiceImpl getInstance(UserDao userDao, DeptService deptService, RoleService roleService) {
        if (instance == null) {
            instance = new UserServiceImpl(userDao, deptService, roleService);
        }
        return instance;
    }

    @Override
    public void create(User user) {
        userDao.save(user);
    }

    @Override
    public List<User> list() {
        return userDao.findAll();
    }

    @Override
    public User getById(Integer id) {
        return userDao.findById(id);
    }

    @Override
    public User getByUsername(String username) {
        return userDao.findByUsername(username);
    }

    @Override
    public void update(User user) {
        userDao.update(user);
    }

    @Override
    public void delete(Integer id) {
        userDao.delete(id);
    }
}

// 5. 视图层
class MainView {
    private static final Scanner input = new Scanner(System.in);
    private static final DeptService deptService = DeptServiceImpl.getInstance(new MemoryDeptDao());
    private static final RoleService roleService = RoleServiceImpl.getInstance(new MemoryRoleDao());
    private static final UserService userService = UserServiceImpl.getInstance(
            new MemoryUserDao(), deptService, roleService);

    public static DeptService getDeptService() {
        return deptService;
    }

    public static RoleService getRoleService() {
        return roleService;
    }

    public static UserService getUserService() {
        return userService;
    }

    public static void show() {
        String menuChoice;
        do {
            printMainMenu();
            menuChoice = input.nextLine();

            switch (menuChoice) {
                case "1" -> DeptView.show();
                case "2" -> RoleView.show();
                case "3" -> UserView.show();
                case "0" -> System.out.println("系统退出");
                default -> System.out.println("无效输入");
            }
        } while (!"0".equals(menuChoice));
        input.close();
    }

    private static void printMainMenu() {
        System.out.print("""
        ===== RBAC系统 =====
        1. 部门管理
        2. 角色管理
        3. 用户管理
        0. 退出系统
        请输入选项: """);
    }
}

class DeptView {
    private static final Scanner input = new Scanner(System.in);
    private static final DeptService service = MainView.getDeptService();

    public static void show() {
        String choice;
        do {
            printMenu();
            choice = input.nextLine();

            switch (choice) {
                case "1" -> createDept();
                case "2" -> listDepts();
                case "3" -> updateDept();
                case "4" -> deleteDept();
                case "0" -> System.out.println("返回上级");
                default -> System.out.println("无效输入");
            }
        } while (!"0".equals(choice));
    }

    private static void printMenu() {
        System.out.print("""
        ===== 部门管理 =====
        1. 创建部门
        2. 部门列表
        3. 更新部门
        4. 删除部门
        0. 返回上级
        请输入选项: """);
    }

    private static void createDept() {
        System.out.print("输入部门名称: ");
        String name = input.nextLine();

        System.out.print("输入联系电话: ");
        String phone = input.nextLine();

        Dept dept = new Dept();
        dept.setName(name);
        dept.setPhone(phone);

        service.create(dept);
        System.out.println("部门创建成功");
    }

    private static void listDepts() {
        System.out.println("===== 部门列表 =====");
        service.list().forEach(dept -> {
            System.out.printf("ID: %d 名称: %s 电话: %s%n",
                    dept.getId(), dept.getName(), dept.getPhone());
        });
    }

    private static void updateDept() {
        System.out.print("输入要修改的部门ID: ");
        int id = Integer.parseInt(input.nextLine());

        Dept dept = service.getById(id);
        if (dept == null) {
            System.out.println("部门不存在");
            return;
        }

        System.out.print("输入新部门名称(当前: " + dept.getName() + "): ");
        String name = input.nextLine();
        if (!name.isEmpty()) dept.setName(name);

        System.out.print("输入新联系电话(当前: " + dept.getPhone() + "): ");
        String phone = input.nextLine();
        if (!phone.isEmpty()) dept.setPhone(phone);

        service.update(dept);
        System.out.println("部门更新成功");
    }

    private static void deleteDept() {
        System.out.print("输入要删除的部门ID: ");
        int id = Integer.parseInt(input.nextLine());

        if (service.getById(id) == null) {
            System.out.println("部门不存在");
            return;
        }

        service.delete(id);
        System.out.println("部门删除成功");
    }
}

class RoleView {
    private static final Scanner input = new Scanner(System.in);
    private static final RoleService service = MainView.getRoleService();

    public static void show() {
        String choice;
        do {
            printMenu();
            choice = input.nextLine();

            switch (choice) {
                case "1" -> createRole();
                case "2" -> listRoles();
                case "3" -> updateRole();
                case "4" -> deleteRole();
                case "0" -> System.out.println("返回上级");
                default -> System.out.println("无效输入");
            }
        } while (!"0".equals(choice));
    }

    private static void printMenu() {
        System.out.print("""
        ===== 角色管理 =====
        1. 创建角色
        2. 角色列表
        3. 更新角色
        4. 删除角色
        0. 返回上级
        请输入选项: """);
    }

    private static void createRole() {
        System.out.print("输入角色名称: ");
        String name = input.nextLine();

        DataScope dataScope = null;
        do {
            System.out.print("输入角色数据访问范围 [个人、部门、全局]: ");//三个选项之中选一个
            String scopeStr = input.nextLine();
            dataScope = DataScope.fromDescription(scopeStr);
            if (dataScope == null) {
                System.out.println("无效的访问范围，请重新输入");
            }
        } while (dataScope == null);

        Role role = new Role();
        role.setName(name);
        role.setDataScope(dataScope);

        service.create(role);
        System.out.println("角色创建成功");
    }

    private static void listRoles() {
        System.out.println("===== 角色列表 =====");
        service.list().forEach(role -> {
            System.out.printf("ID: %d 名称: %s 数据范围: %s%n",
                    role.getId(), role.getName(), role.getDataScope().getDescription());
        });
    }

    private static void updateRole() {
        System.out.print("输入要修改的角色ID: ");
        int id = Integer.parseInt(input.nextLine());

        Role role = service.getById(id);
        if (role == null) {
            System.out.println("角色不存在");
            return;
        }

        System.out.print("输入新角色名称(当前: " + role.getName() + "): ");
        String name = input.nextLine();
        if (!name.isEmpty()) role.setName(name);

        DataScope dataScope = null;
        do {
            System.out.print("输入角色数据访问范围 [个人、部门、全局] (当前: " +
                    role.getDataScope().getDescription() + "): ");
            String scopeStr = input.nextLine();

            if (scopeStr.isEmpty()) {
                dataScope = role.getDataScope();
                break;
            }

            dataScope = DataScope.fromDescription(scopeStr);
            if (dataScope == null) {
                System.out.println("无效的访问范围，请重新输入");
            }
        } while (dataScope == null);

        role.setDataScope(dataScope);

        service.update(role);
        System.out.println("角色更新成功");
    }

    private static void deleteRole() {
        System.out.print("输入要删除的角色ID: ");
        int id = Integer.parseInt(input.nextLine());

        if (service.getById(id) == null) {
            System.out.println("角色不存在");
            return;
        }

        service.delete(id);
        System.out.println("角色删除成功");
    }
}

class UserView {
    private static final Scanner input = new Scanner(System.in);
    private static final UserService userService = MainView.getUserService();
    private static final DeptService deptService = MainView.getDeptService();
    private static final RoleService roleService = MainView.getRoleService();

    public static void show() {
        String choice;
        do {
            printMenu();
            choice = input.nextLine();

            switch (choice) {
                case "1" -> createUser();
                case "2" -> listUsers();
                case "3" -> updateUser();
                case "4" -> deleteUser();
                case "0" -> System.out.println("返回上级");
                default -> System.out.println("无效输入");
            }
        } while (!"0".equals(choice));
    }

    private static void printMenu() {
        System.out.print("""
        ===== 用户管理 =====
        1. 创建用户
        2. 用户列表
        3. 更新用户
        4. 删除用户
        0. 返回上级
        请输入选项: """);
    }

    private static void createUser() {
        System.out.print("输入用户名: ");
        String username = input.nextLine();

        System.out.print("输入密码: ");
        String password = input.nextLine();

        System.out.print("输入用户状态(true/false): ");
        Boolean enabled = Boolean.parseBoolean(input.nextLine());

        // 选择部门
        listDeptsForSelection();
        System.out.print("选择部门ID: ");
        int deptId = Integer.parseInt(input.nextLine());
        Dept dept = deptService.getById(deptId);
        if (dept == null) {
            System.out.println("无效的部门ID，用户创建失败");
            return;
        }

        // 选择角色
        listRolesForSelection();
        System.out.print("选择角色ID: ");
        int roleId = Integer.parseInt(input.nextLine());
        Role role = roleService.getById(roleId);
        if (role == null) {
            System.out.println("无效的角色ID，用户创建失败");
            return;
        }

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);
        user.setEnabled(enabled);
        user.setDept(dept);
        user.setRole(role);

        userService.create(user);
        System.out.println("用户创建成功");
    }

    private static void listUsers() {
        System.out.println("===== 用户列表 =====");
        userService.list().forEach(user -> {
            System.out.printf("ID: %d 用户名: %s 部门: %s 角色: %s 状态: %s%n",
                    user.getId(),
                    user.getUsername(),
                    user.getDept() != null ? user.getDept().getName() : "无",
                    user.getRole() != null ? user.getRole().getName() : "无",
                    user.getEnabled() ? "启用" : "禁用");
        });
    }

    private static void updateUser() {
        System.out.print("输入要修改的用户ID: ");
        int id = Integer.parseInt(input.nextLine());

        User user = userService.getById(id);
        if (user == null) {
            System.out.println("用户不存在");
            return;
        }

        System.out.print("输入新用户名(当前: " + user.getUsername() + "): ");
        String username = input.nextLine();
        if (!username.isEmpty()) user.setUsername(username);

        System.out.print("输入新密码(直接回车不修改): ");
        String password = input.nextLine();
        if (!password.isEmpty()) user.setPassword(password);

        System.out.print("输入新用户状态(true/false)(当前: " + user.getEnabled() + "): ");
        String enabledStr = input.nextLine();
        if (!enabledStr.isEmpty()) {
            user.setEnabled(Boolean.parseBoolean(enabledStr));
        }

        // 更新部门
        listDeptsForSelection();
        System.out.print("选择新部门ID(直接回车不修改): ");
        String deptIdStr = input.nextLine();
        if (!deptIdStr.isEmpty()) {
            int deptId = Integer.parseInt(deptIdStr);
            Dept dept = deptService.getById(deptId);
            if (dept == null) {
                System.out.println("无效的部门ID，部门不更新");
            } else {
                user.setDept(dept);
            }
        }

        // 更新角色
        listRolesForSelection();
        System.out.print("选择新角色ID(直接回车不修改): ");
        String roleIdStr = input.nextLine();
        if (!roleIdStr.isEmpty()) {
            int roleId = Integer.parseInt(roleIdStr);
            Role role = roleService.getById(roleId);
            if (role == null) {
                System.out.println("无效的角色ID，角色不更新");
            } else {
                user.setRole(role);
            }
        }

        userService.update(user);
        System.out.println("用户更新成功");
    }

    private static void deleteUser() {
        System.out.print("输入要删除的用户ID: ");
        int id = Integer.parseInt(input.nextLine());

        if (userService.getById(id) == null) {
            System.out.println("用户不存在");
            return;
        }

        userService.delete(id);
        System.out.println("用户删除成功");
    }

    private static void listDeptsForSelection() {
        System.out.println("===== 部门列表 =====");
        deptService.list().forEach(dept -> {
            System.out.printf("ID: %d 名称: %s%n", dept.getId(), dept.getName());
        });
    }

    private static void listRolesForSelection() {
        System.out.println("===== 角色列表 =====");
        roleService.list().forEach(role -> {
            System.out.printf("ID: %d 名称: %s 数据范围: %s%n",
                    role.getId(), role.getName(), role.getDataScope().getDescription());
        });
    }
}

// 6. 主程序
public class Main {
    public static void main(String[] args) {
        MainView.show();
    }
}
